//
//  BattleScene.cpp
//  fingeradvanture
//
//  Created by 8089HaiWan1 on 16/5/14.
//
//

#include "BattleScene.h"
#include "GameManager.hpp"
#include "MonsterDen.hpp"
#include "Utils.hpp"

USING_NS_CC;

//物理引擎标识
int ball1Mask = 1 << 0;//球1
int ball2Mask = 1 << 1;//球2
int wallMask = 1 << 2;//地面

BattleScene::~BattleScene()
{
    CC_SAFE_DELETE(m_world);
    CC_SAFE_DELETE(myContactListener);
}


Scene* BattleScene::createScene()
{
    // 'scene' is an autorelease object
    auto scene = Scene::create();
    //scene->getPhysicsWorld()->setDebugDrawMask(PhysicsWorld::DEBUGDRAW_ALL);
    
    // 'layer' is an autorelease object
    auto layer = BattleScene::create();
    
    // add layer as a child to scene
    scene->addChild(layer);
    
    // return the scene
    return scene;
}

// on "init" you need to initialize your instance
bool BattleScene::init()
{
    //////////////////////////////
    // 1. super init first
    if ( !Layer::init() )
    {
        return false;
    }
    this->player = 0;
    Vec2 origin = Director::getInstance()->getVisibleOrigin();
    
    /////////////////////////////
    // 2. add a menu item with "X" image, which is clicked to quit the program
    //    you may modify it.
    
    auto startLabel = LabelTTF::create("touch to play game～",  "Arial", 20); // create a start botton
    MenuItemLabel *startGame = MenuItemLabel::create(startLabel, this, menu_selector(BattleScene::menuCloseCallback));
    startGame->runAction(Blink::create(10, 20));
    
    // create menu, it's an autorelease object
    auto menu = Menu::create(startGame, NULL);
    menu->setPosition(Vec2::ZERO);
    this->addChild(menu, 1);
    
    //initialize the Contact Listener
    b2Vec2 gravity = b2Vec2(0.0f, 0.0f);
    b2World* world = new b2World(gravity);
    setPhyWorld(world);
    m_world->SetAllowSleeping(true);
    m_world->SetContinuousPhysics(true);
    
    b2BodyDef groundBodyDef;
    Size screenSize = Director::getInstance()->getVisibleSize();
    groundBodyDef.position.Set(screenSize.width/2/PTM_RATIO,
                               screenSize.height/2/PTM_RATIO); // bottom-left corner
    
    // Call the body factory which allocates memory for the ground body
    // from a pool and creates the ground box shape (also from a pool).
    // The body is also added to the world.
    b2Body* groundBody = world->CreateBody(&groundBodyDef);
    
    // Define the ground box shape.
    b2PolygonShape groundBox;
    
    // bottom
    groundBox.SetAsBox(screenSize.width/2/PTM_RATIO, 0, b2Vec2(0, -screenSize.height/2/PTM_RATIO), 0);
    groundBody->CreateFixture(&groundBox, 0);
    
    // top
    groundBox.SetAsBox(screenSize.width/2/PTM_RATIO, 0, b2Vec2(0, screenSize.height/2/PTM_RATIO), 0);
    groundBody->CreateFixture(&groundBox, 0);
    
    // left
    groundBox.SetAsBox(0, screenSize.height/2/PTM_RATIO, b2Vec2(-screenSize.width/2/PTM_RATIO, 0), 0);
    groundBody->CreateFixture(&groundBox, 0);
    
    // right
    groundBox.SetAsBox(0, screenSize.height/2/PTM_RATIO, b2Vec2(screenSize.width/2/PTM_RATIO, 0), 0);
    groundBody->CreateFixture(&groundBox, 0);
    
    myContactListener = new MyContactListener();
    m_world->SetContactListener(myContactListener);
    
    
    debugDraw = new GLESDebugDraw(PTM_RATIO);
    m_world->SetDebugDraw(debugDraw);
    uint32 flags = 0;
    flags += b2Draw::e_shapeBit;
    flags += b2Draw::e_jointBit;
    debugDraw->SetFlags(flags);
    ////////////////// End Of Block //////////////////
    
    /////////////////////////////
    auto dispatcher = Director::getInstance()->getEventDispatcher();
    auto listener = EventListenerTouchOneByOne::create();
    listener->onTouchBegan = CC_CALLBACK_2(BattleScene::onTouchBegan,this);
    listener->onTouchMoved = CC_CALLBACK_2(BattleScene::onTouchMoved,this);
    listener->onTouchEnded = CC_CALLBACK_2(BattleScene::onTouchEnded,this);
    listener->setSwallowTouches(true);//不向下传递触摸
    dispatcher->addEventListenerWithSceneGraphPriority(listener,this);
    
    this->scheduleUpdate();
    
    return true;
}

void BattleScene::update(float delta)
{
    //CCLOG("%d", this->contactListener->getReferenceCount());
    //清理无用的Monster Node
    MonsterDen::getInstance()->recycleUselessTroops(m_world);
    
    // Instruct the world to perform a single step of simulation. It is
    // generally best to keep the time step and iterations fixed.
    int velocityIterations = 8;
    int positionIterations = 1;
    m_world->Step(delta, velocityIterations, positionIterations);
    
    for(b2Body *b = m_world->GetBodyList();b; b = b->GetNext())
    {
        if(b->GetUserData() != NULL)
        {
            Sprite* sprite = (Sprite*)b->GetUserData();
            if(sprite)
            {
                b2Vec2 b2Position = b2Vec2(sprite->getPositionX()/PTM_RATIO,sprite->getPositionY()/PTM_RATIO);
                float32 bAngle = -1*CC_DEGREES_TO_RADIANS(sprite->getRotation());
                b->SetTransform(b2Position, bAngle);
            }
            
        }
    }
    
    //呼叫支援，需要新的Monster Node
    Vector<Node *> troop = MonsterDen::getInstance()->decideToSendTroops(m_world);
    for(auto it = troop.begin(); it != troop.end(); it++)
    {
        this->addChild(*it);
    }
    
    Layer::update(delta);
    
    
    //清理无用的Monster Node
   // MonsterDen::getInstance()->recycleUselessTroops(m_world);
}

void BattleScene::heroEnter(float x, float y)
{
    this->player = Utils::createTestHero(m_world); //createTestHero
    this->player->setPosition(Vec2(x,y));
    this->addChild(this->player);
    
    GameManager::getInstance()->heroEnter();
}


void BattleScene::registerContactListener()
{
    //Director::getInstance()->getEventDispatcher()->addEventListenerWithSceneGraphPriority(this->contactListener,this);
}

void BattleScene::deregisterContactListener()
{
    //Director::getInstance()->getEventDispatcher()->removeEventListener(this->contactListener);
}

bool BattleScene::onContactBegin(const PhysicsContact &contact)
{
    this->deregisterContactListener();
    GameManager::getInstance()->heroDied();
    return true;
}

bool BattleScene::onTouchBegan(Touch *pTouch, Event *pEvent)
{
    CCLOG("hhhaha");
    Point touchPoint = pTouch->getLocation();
    
    this->registerContactListener();
    
    if(Director::getInstance()->isPaused())
    {
        this->player->setPosition(touchPoint);
        GameManager::getInstance()->gameResume();
    }
    else
    {
        heroEnter(touchPoint.x, touchPoint.y);
    }
    
    return true;
}

void BattleScene::onTouchMoved(Touch *pTouch, Event *pEvent)
{
    Point touchpoint = pTouch->getLocation();
    if(this->player){}
        this->player->setPosition(touchpoint);
}

void BattleScene::onTouchEnded(Touch *pTouch, Event *pEvent)
{
    this->deregisterContactListener();
    GameManager::getInstance()->heroExit();
}

void BattleScene::menuCloseCallback(Ref* pSender)
{
    Director::getInstance()->end();
    
#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
    exit(0);
#endif
}

void BattleScene::draw(Renderer *renderer,const cocos2d::Mat4&transform,uint32_t flags)
{
    GL::enableVertexAttribs(GL::VERTEX_ATTRIB_FLAG_POSITION);
    m_world->DrawDebugData();
    CHECK_GL_ERROR_DEBUG();
}
